<template>
    <view class="container">
      <!-- 控制面板 -->
      <view class="control-panel">
        <view class="panel-header">
          <text class="panel-title">控制面板</text>
          <view class="button-group">
            <button
              class="control-button"
              :class="{ 'button-primary': !isRunning, 'button-danger': isRunning }"
              @click="isRunning ? stopPlunder() : startPlunder()"
            >
              <text class="button-icon">{{ isRunning ? '⏹' : '▶' }}</text>
              {{ isRunning ? '停止' : '启动' }}
            </button>
            <button
              class="control-button button-secondary"
              @click="attackPrepare(0)"
            >
              <text class="button-icon">🔍</text>
              查询状态
            </button>
            <button
              class="control-button button-secondary"
              @click="attackPrepare(1)"
            >
              <text class="button-icon">🔄</text>
              刷新状态
            </button>
          </view>
        </view>
  
        <!-- 状态信息 -->
        <view class="status-info">
          <view class="status-item">
            <text class="status-label">运行状态:</text>
            <text class="status-value" :class="{ 'status-running': isRunning }">{{ status }}</text>
          </view>
          <view class="status-item">
            <text class="status-label">倒计时:</text>
            <text class="status-value">{{ countdown }}</text>
          </view>
          <view class="status-item">
            <text class="status-label">定时状态:</text>
            <text class="status-value" :class="{ 
              'status-active': isWithinTimeRange() && !manuallyStopped,
              'status-manual-stop': manuallyStopped 
            }">
              {{ manuallyStopped ? '手动停止' : (isWithinTimeRange() ? '运行时段内' : '运行时段外') }}
            </text>
          </view>
          <view class="status-item">
            <text class="status-label">当前时间:</text>
            <text class="status-value">{{ currentTime }}</text>
          </view>
        </view>
  
        <!-- 定时设置 -->
        <view class="schedule-panel">
          <view class="schedule-header">
            <text class="schedule-title">定时设置</text>
          </view>
          <view class="schedule-content">
            <view class="time-input-group">
              <view class="time-input">
                <text class="time-label">开始时间</text>
                <input
                  type="time"
                  v-model="config.startTime"
                  class="time-picker"
                  @change="saveConfig"
                />
              </view>
              <view class="time-input">
                <text class="time-label">结束时间</text>
                <input
                  type="time"
                  v-model="config.stopTime"
                  class="time-picker"
                  @change="saveConfig"
                />
              </view>
            </view>
          </view>
        </view>
  
        <!-- 配置表单 -->
        <config-form
          :is-running="isRunning"
          :initial-config="config"
          @update:config="updateConfig"
        />
      </view>
  
      <!-- 角色列表 -->
      <view class="role-list">
        <view class="role-list-header">
          <text class="role-list-title">角色列表</text>
          <text class="role-list-count">共 {{ info.roles.length }} 个角色</text>
        </view>
        <view class="role-grid">
          <view v-for="(role, index) in info.roles" :key="index" class="role-card">
            <view class="role-header">
              <text class="role-nickname">{{ role.nickname }}</text>
              <text class="role-stone" :class="{ 'highlight': role.stone > config.threshold }">
                {{ role.stone }} 灵石
              </text>
            </view>
            <view class="role-info">
              <text class="role-level">{{ role.name }} {{ role.layer }}层</text>
              <text class="role-detail">等级: Lv.{{ role.level }}</text>
              <text v-if="role.reborn" class="role-detail">转生: {{ role.reborn }}{{ role.rebornLevel }}</text>
              <text v-if="role.equip && role.equip.length > 0" class="role-equip">
                装备: {{ role.equip.join(', ') }}
              </text>
            </view>
          </view>
        </view>
      </view>
  
      <!-- 提示信息 -->
      <view class="tips" v-if="info.attackTips">
        <text class="tips-icon">💡</text>
        <text class="tips-content">{{ info.attackTips }}</text>
      </view>
  
      <!-- 日志面板 -->
      <log-panel
        :logs="logs"
        :scroll-to="scrollTo"
        @clear="clearLog"
      />
  
      <!-- 统计面板 -->
      <stats-panel
        :stats="plunderStats"
      />
    </view>
  </template>
  
  <script setup>
  import { ref, computed, onMounted, onUnmounted } from 'vue';
  import StatusCard from '@/components/StatusCard.vue';
  import ConfigForm from '@/components/ConfigForm.vue';
  import LogPanel from '@/components/LogPanel.vue';
  import StatsPanel from '@/components/StatsPanel.vue';
  
  // 常量定义
  const BASE_URL = 'https://farm-api.lucklyworld.com';
  const PREPARE_API = '/v8/api/game/bead/plunder/attack/prepare';
  const ATTACK_API = '/v8/api/game/bead/plunder/attack/start';
  const MAX_LOG_LINES = 1000;
  const MAX_RECORDS = 100;
  const RETRY_ATTEMPTS = 5;
  const LOG_CLEANUP_INTERVAL = 3600000; // 1小时清理一次
  const LOG_MAX_AGE = 3600000; // 日志保留1小时
  const RATE_LIMIT = {
    prepare: { maxRequests: 10, timeWindow: 60000 },
    attack: { maxRequests: 5, timeWindow: 60000 }
  };
  
  // 状态管理
  const isRunning = ref(false);
  const status = ref('已停止');
  const countdown = ref('N/A');
  const logs = ref([]);
  const scrollTo = ref('');
  const manuallyStopped = ref(false);
  const info = ref({
    stone: { passive: '0', plunder: '0' },
    refresh: { used: 0, total: 0 },
    roles: [],
    attackTips: ''
  });
  const config = ref({
    nicknames: [],
    uid: '',
    roleId: '',
    token: '',
    threshold: '168.0',
    quickRefreshCount: '3',
    quickRefreshDuration: '40',
    quickRefreshInterval: '4',
    startTime: '10:00',
    stopTime: '19:00'
  });
  const plunderStats = ref({
    totalAttempts: 0,
    successfulPlunders: 0,
    totalStones: 0.0,
    records: [],
    nicknameStats: {}
  });
  let timerId = null;
  
  // 计算属性
  const successRate = computed(() => {
    return plunderStats.value.totalAttempts > 0
      ? ((plunderStats.value.successfulPlunders / plunderStats.value.totalAttempts) * 100).toFixed(2)
      : '0.00';
  });
  
  // 日志记录
  const log = (message) => {
    const timestamp = new Date().toLocaleTimeString();
    const logEntry = `[${timestamp}] ${message}`;
    logs.value.unshift(logEntry);
    if (logs.value.length > MAX_LOG_LINES) {
      logs.value.pop();
    }
    scrollTo.value = logEntry;
    try {
      uni.setStorageSync('plunder_logs', logs.value);
    } catch (e) {
      console.error('保存日志失败:', e);
    }
  };
  
  // 清除日志
  const clearLog = () => {
    logs.value = [];
    scrollTo.value = '';
    try {
      uni.removeStorageSync('plunder_logs');
    } catch (e) {
      console.error('清除日志失败:', e);
    }
  };
  
  // 检查 token 是否有效
  const isTokenValid = () => {
    const token = config.value.token || '';
    return !!token; // 只要有 token 就认为是有效的
  };
  
  // 解析 token 中的 uid
  const parseTokenUid = (token) => {
    if (!token) {
      console.log('Token 为空，跳过解析');
      return '';
    }
  
    try {
      // 尝试从 token 中解析 uid，但不验证格式
      const parts = token.split('.');
      if (parts.length >= 2) {
        const payloadPart = parts[1];
        if (payloadPart) {
          try {
            // 将 URL 安全的 base64 转换为标准 base64
            const standardBase64 = payloadPart.replace(/-/g, '+').replace(/_/g, '/');
            // 添加 padding
            const paddedBase64 = standardBase64 + '='.repeat((4 - standardBase64.length % 4) % 4);
            // 解码
            const decodedPayload = decodeURIComponent(escape(atob(paddedBase64)));
            // 从解码后的 payload 中提取 jti
            const match = decodedPayload.match(/"jti"\s*:\s*"(\d+)"/);
            if (match) {
              const uid = match[1];
              console.log('成功从 Token 提取 UID:', uid);
              return uid;
            }
          } catch (e) {
            console.log('提取 UID 失败:', e.message);
          }
        }
      }
      return '';
    } catch (e) {
      console.error('Token 解析失败:', e);
      return '';
    }
  };
  
  // 生成随机字符串
  const generateRandomString = (length) => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  };
  
  // 倒计时到下一个五分钟
  const secondsToNextFiveMinute = () => {
    const now = new Date();
    const minutes = now.getMinutes();
    const seconds = now.getSeconds();
    const nextFiveMinute = Math.ceil(minutes / 5) * 5;
    const diffMinutes = nextFiveMinute - minutes;
    const totalSeconds = diffMinutes * 60 - seconds;
    countdown.value = `${Math.floor(totalSeconds / 60)}:${(totalSeconds % 60).toString().padStart(2, '0')}`;
  };
  
  // 清理日志
  const cleanupLogs = () => {
    const now = Date.now();
    logs.value = logs.value.filter(log => {
      const timestamp = log.match(/\[(.*?)\]/)?.[1];
      if (!timestamp) return true;
      const logTime = new Date(`2025 ${timestamp}`).getTime();
      return now - logTime < LOG_MAX_AGE;
    });
  };
  
  // 更新统计
  const updateStats = (nickname, stones, targetRoleId) => {
    const record = {
      timestamp: new Date().toLocaleString(),
      nickname,
      targetRoleId,
      stones
    };
    plunderStats.value.records.unshift(record);
    if (plunderStats.value.records.length > MAX_RECORDS) {
      plunderStats.value.records.pop();
    }
    if (!plunderStats.value.nicknameStats[nickname]) {
      plunderStats.value.nicknameStats[nickname] = { count: 0, stones: 0 };
    }
    plunderStats.value.nicknameStats[nickname].count++;
    plunderStats.value.nicknameStats[nickname].stones += stones;
  };
  
  // 检查是否在运行时间段内
  const isWithinTimeRange = () => {
    if (manuallyStopped.value) return false;
    const now = new Date();
    const currentTime = now.getHours() * 60 + now.getMinutes();
    const [startHour, startMinute] = config.value.startTime.split(':').map(Number);
    const [stopHour, stopMinute] = config.value.stopTime.split(':').map(Number);
    const startTime = startHour * 60 + startMinute;
    const stopTime = stopHour * 60 + stopMinute;
  
    // 处理跨天情况
    if (startTime <= stopTime) {
      return currentTime >= startTime && currentTime < stopTime;
    } else {
      return currentTime >= startTime || currentTime < stopTime;
    }
  };
  
  // 定时检查
  const checkSchedule = () => {
    if (isWithinTimeRange()) {
      if (!isRunning.value && !manuallyStopped.value) {
        // 检查 token 是否有效
        if (!isTokenValid()) {
          if (!config.value.token) {
            log('Token 为空，请先设置有效的 Token');
            status.value = 'Token 未设置';
          } else {
            log('Token 格式不正确，请确保复制完整的 Token');
            status.value = 'Token 格式错误';
          }
          // 停止定时检查，避免重复尝试
          if (timerId) {
            clearInterval(timerId);
            timerId = null;
          }
          return;
        }
        
        log('到达定时开启时间，自动启动抢夺');
        startPlunder();
      }
    } else {
      if (isRunning.value) {
        log('到达定时停止时间，自动停止抢夺');
        isRunning.value = false;
        status.value = '已停止（定时）';
        countdown.value = 'N/A';
      }
    }
  };
  
  // 查询灵珠
  const attackPrepare = async (isRefresh) => {
    const token = config.value.token || '';
    console.log('准备发送请求，token 信息:', {
      exists: !!token,
      length: token.length,
      value: token.substring(0, 20) + '...'
    });
  
    if (!token) {
      log('错误: Token 为空');
      status.value = 'Token 未设置';
      return null;
    }
  
    const headers = {
      'User-Agent': 'com.caike.lomo/4.2.6 (Linux; U; Android 12; zh-cn) (91416; 402060)bbcbce6e97449754',
      'Channel': 'official',
      'ANDROIDID': 'a7b19730952f1068',
      'IMEI': '352746026192015',
      'test-encrypt': '0',
      'token': token,
      'Content-Type': 'application/json; charset=utf-8'
    };
  
    const requestData = {
      roleId: config.value.roleId,
      isRefresh: isRefresh ? 1 : 0,
      trayType: 0
    };
  
    console.log('查询请求参数:', {
      url: `${BASE_URL}${PREPARE_API}?uid=${config.value.uid}&version=2.0.0`,
      headers: { ...headers, token: '***' },
      data: requestData
    });
  
    for (let attempt = 0; attempt < RETRY_ATTEMPTS; attempt++) {
      try {
        status.value = `查询灵珠 (尝试 ${attempt + 1}/${RETRY_ATTEMPTS})...`;
        const response = await uni.request({
          url: `${BASE_URL}${PREPARE_API}?uid=${config.value.uid}&version=2.0.0`,
          method: 'POST',
          header: headers,
          data: requestData,
          timeout: 10000
        });
  
        // 记录响应状态
        console.log('请求响应:', {
          statusCode: response.statusCode,
          headers: response.header,
          data: typeof response.data === 'string' ? response.data.substring(0, 100) + '...' : 'Object'
        });
  
        if (response.statusCode === 200) {
          const data = response.data;
          if (!data) {
            log('收到空响应数据');
            throw new Error('Empty response data');
          }
  
          // 记录响应数据（隐藏敏感信息）
          console.log('查询响应:', {
            statusCode: response.statusCode,
            data: typeof data === 'string' ? data.substring(0, 100) + '...' : 'Object'
          });
  
          return data;
        } else {
          log(`请求失败 (${response.statusCode}): ${response.data?.message || '未知错误'}`);
          if (response.statusCode === 400 && response.data?.message?.includes('JWT')) {
            log('Token 格式错误，请确保复制完整的 Token');
            status.value = 'Token 格式错误';
            return null;
          }
          throw new Error(`HTTP ${response.statusCode}`);
        }
      } catch (e) {
        console.error('请求失败:', e);
        if (attempt === RETRY_ATTEMPTS - 1) {
          log(`查询失败: ${e.message}`);
          throw e;
        }
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    }
    return null;
  };
  
  // 执行抢夺
  const executePlunder = async (targetRoleId, nickname) => {
    const headers = {
      'User-Agent': 'com.caike.lomo/4.2.6 (Linux; U; Android 12; zh-cn) (91416; 402060)bbcbce6e97449754',
      'Channel': 'official',
      'ANDROIDID': 'a7b19730952f1068',
      'IMEI': '352746026192015',
      'test-encrypt': '0',
      'token': config.value.token,
      'Content-Type': 'application/json; charset=utf-8'
    };
  
    const payload = {
      roleId: config.value.roleId,
      dRoleId: targetRoleId,
      trayType: 0
    };
  
    console.log('抢夺请求参数:', {
      url: `${BASE_URL}${ATTACK_API}?uid=${config.value.uid}&version=2.0.0`,
      headers: { ...headers, token: '***' },
      data: payload,
      tokenLength: config.value.token.length,
      tokenParts: config.value.token.split('.').length
    });
  
    for (let attempt = 0; attempt < RETRY_ATTEMPTS; attempt++) {
      try {
        status.value = `抢夺 ${nickname} (尝试 ${attempt + 1}/${RETRY_ATTEMPTS})...`;
        const response = await uni.request({
          url: `${BASE_URL}${ATTACK_API}?uid=${config.value.uid}&version=2.0.0`,
          method: 'POST',
          data: payload,
          header: headers,
          timeout: 10000
        });
  
        plunderStats.value.totalAttempts++;
        if (response.statusCode === 200) {
          const result = response.data;
          if (result.plunderResult?.status === 1) {
            const stones = parseFloat(result.plunderResult.stone);
            plunderStats.value.successfulPlunders++;
            plunderStats.value.totalStones += stones;
            log(`抢夺成功，昵称: ${nickname}, 获得灵石: ${stones}`);
            status.value = `抢夺成功: ${nickname}, ${stones} 灵石`;
            updateStats(nickname, stones, targetRoleId);
            return result;
          } else {
            log(`抢夺失败，昵称: ${nickname}`);
            status.value = `抢夺失败: ${nickname}`;
          }
          return result;
        } else if (response.statusCode === 429) {
          log('请求过于频繁，暂停 30 秒');
          status.value = '请求限流，暂停 30 秒';
          await new Promise(resolve => setTimeout(resolve, 30000));
          continue;
        } else {
          log(`抢夺失败，昵称: ${nickname}, 状态码: ${response.statusCode}`);
          status.value = `抢夺失败: ${nickname}, 状态码 ${response.statusCode}`;
          return null;
        }
      } catch (e) {
        log(`抢夺出错: ${e.message}`);
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
      }
    }
    log('达到最大重试次数，抢夺失败');
    status.value = '抢夺失败，达到最大重试次数';
    return null;
  };
  
  // 主循环
  const runCycle = async () => {
    if (!isRunning.value) return;
    log('开始自动抢夺灵珠，持续运行模式');
    let cycleCount = 0;
    let firstCycle = true;
    const nicknameSet = new Set(config.value.nicknames);
  
    while (isRunning.value && isWithinTimeRange()) {
      cycleCount++;
      log(`第 ${cycleCount} 次循环开始`);
      status.value = `循环 ${cycleCount} 开始`;
  
      const isRefresh = firstCycle ? 0 : 1;
      if (isRefresh) {
        await new Promise(resolve => setTimeout(resolve, 3000));
      }
  
      const response = await attackPrepare(isRefresh);
      if (!response) {
        log('查询失败，等待10秒后重试');
        status.value = '查询失败，等待10秒';
        await new Promise(resolve => setTimeout(resolve, 10000 + Math.random() * 2000));
        continue;
      }
  
      if (response.error === 'not_registered') {
        return;
      }
  
      if (response.error === 'refresh_exhausted') {
        const roleList = response.roleList || [];
        const maxStoneRole = roleList.reduce((max, role) => {
          const stones = parseFloat(role.stone || 0);
          return stones > parseFloat(max.stone || 0) ? role : max;
        }, { stone: 0 });
  
        if (maxStoneRole.roleId) {
          log(`抢夺灵石最高的角色: ${maxStoneRole.nickname} (灵石: ${maxStoneRole.stone})`);
          await executePlunder(maxStoneRole.roleId, maxStoneRole.nickname);
          await new Promise(resolve => setTimeout(resolve, 3000 + Math.random() * 2000));
        } else {
          log('无可用角色，等待10秒后重试');
          status.value = '无可用角色，等待10秒';
          await new Promise(resolve => setTimeout(resolve, 10000 + Math.random() * 2000));
        }
        continue;
      }
  
      firstCycle = false;
      const roleList = response.roleList || [];
      const refreshUsed = response.refreshNum?.used || 0;
      const refreshTotal = response.refreshNum?.total || 10;
  
      let targetRole = null;
      for (const role of roleList) {
        const nickname = role.nickname?.toLowerCase().trim();
        const stones = parseFloat(role.stone || 0);
        if (nicknameSet.has(nickname)) {
          targetRole = { roleId: role.roleId, nickname, stone: stones };
          log(`找到名单中的角色: ${nickname}, 灵石: ${stones}`);
          status.value = `找到目标: ${nickname}, 灵石 ${stones}`;
          break;
        }
      }
  
      if (targetRole) {
        if (targetRole.stone > parseFloat(config.value.threshold)) {
          log(`灵石满足条件 (>${config.value.threshold})，抢夺角色: ${targetRole.nickname}`);
          await executePlunder(targetRole.roleId, targetRole.nickname);
          log('抢夺完成，等待3秒后继续下一次循环');
          status.value = '抢夺完成，等待3秒';
          await new Promise(resolve => setTimeout(resolve, 3000 + Math.random() * 2000));
        } else {
          // 灵石不足，执行快速刷新逻辑
          let quickRefreshCount = 0;
          const quickRefreshCountMax = parseInt(config.value.quickRefreshCount) || 3;
          const quickRefreshDuration = parseInt(config.value.quickRefreshDuration) || 40;
          const quickRefreshInterval = parseInt(config.value.quickRefreshInterval) || 4;
  
          while (quickRefreshCount < quickRefreshCountMax && isRunning.value) {
            quickRefreshCount++;
            log(`灵石不足 (<= ${config.value.threshold})，目标: ${targetRole.nickname}，第 ${quickRefreshCount}/${quickRefreshCountMax} 次快速检测`);
            status.value = `快速检测: ${targetRole.nickname} (${quickRefreshCount}/${quickRefreshCountMax})`;
  
            // 直接进入快速检测模式
            log('进入快速检测模式');
            const quickStartTime = Date.now();
            let lastCheckTime = quickStartTime;
            let shouldBreak = false;
  
            while (Date.now() - quickStartTime < quickRefreshDuration * 1000 && isRunning.value && !shouldBreak) {
              const currentTime = Date.now();
              const timeSinceLastCheck = (currentTime - lastCheckTime) / 1000;
  
              if (timeSinceLastCheck >= quickRefreshInterval) {
                if (timeSinceLastCheck > quickRefreshInterval + 0.5) {
                  log(`检测间隔异常: ${timeSinceLastCheck.toFixed(1)}秒`);
                }
  
                const refreshResponse = await attackPrepare(0);
                if (!refreshResponse) {
                  log('快速检测失败，等待3秒重试');
                  status.value = `快速检测: ${targetRole.nickname} (失败重试)`;
                  await new Promise(resolve => setTimeout(resolve, 3000));
                  continue;
                }
  
                if (refreshResponse.error === 'refresh_exhausted') {
                  log(`快速检测中刷新次数已用尽，继续等待目标角色: ${targetRole.nickname}`);
                  status.value = `快速检测: ${targetRole.nickname} (刷新次数用尽)`;
                  await new Promise(resolve => setTimeout(resolve, 3000));
                  continue;
                }
  
                const refreshRoleList = refreshResponse.roleList || [];
                let targetFound = false;
  
                for (const role of refreshRoleList) {
                  if (role.roleId === targetRole.roleId) {
                    targetFound = true;
                    targetRole.stone = parseFloat(role.stone || 0);
                    log(`检测灵石: ${targetRole.nickname} (${targetRole.stone})`);
                    status.value = `快速检测: ${targetRole.nickname} (${targetRole.stone})`;
  
                    if (targetRole.stone > parseFloat(config.value.threshold)) {
                      log(`灵石满足条件 (>${config.value.threshold})，抢夺角色: ${targetRole.nickname}`);
                      await executePlunder(targetRole.roleId, targetRole.nickname);
                      log('抢夺完成，退出快速检测');
                      status.value = '抢夺完成';
                      await new Promise(resolve => setTimeout(resolve, 3000 + Math.random() * 2000));
                      shouldBreak = true;
                    }
                    break;
                  }
                }
  
                if (!targetFound) {
                  log(`目标角色 ${targetRole.nickname} 已不在列表中，退出快速检测`);
                  status.value = `目标 ${targetRole.nickname} 不在列表`;
                  shouldBreak = true;
                }
  
                lastCheckTime = currentTime;
              } else {
                await new Promise(resolve => setTimeout(resolve, Math.max(10, (quickRefreshInterval - timeSinceLastCheck) * 1000)));
              }
            }
  
            if (Date.now() - quickStartTime >= quickRefreshDuration * 1000) {
              log(`第 ${quickRefreshCount}/${quickRefreshCountMax} 次快速检测结束`);
              status.value = `快速检测: ${targetRole.nickname} (完成)`;
            }
  
            if (shouldBreak) {
              log(`快速检测退出，原因: ${targetRole.stone > parseFloat(config.value.threshold) ? '灵石满足条件' : !targetFound ? '目标不在列表' : '刷新次数耗尽'}`);
              break;
            }
  
            if (quickRefreshCount === quickRefreshCountMax) {
              log(`已完成 ${quickRefreshCountMax} 次快速检测，灵石仍不足，强制抢夺: ${targetRole.nickname}`);
              status.value = `强制抢夺: ${targetRole.nickname}`;
              let retryCount = 0;
              const maxRetries = 3;
  
              while (retryCount < maxRetries && isRunning.value) {
                const result = await executePlunder(targetRole.roleId, targetRole.nickname);
                if (result?.plunderResult?.status === 1) {
                  log('抢夺成功，退出快速检测');
                  status.value = '抢夺成功';
                  break;
                } else if (result && result.message?.includes('该玩家正在被挑战')) {
                  retryCount++;
                  if (retryCount < maxRetries) {
                    log(`目标正在被挑战，1秒后第${retryCount + 1}次重试`);
                    status.value = `重试抢夺: ${targetRole.nickname} (${retryCount + 1}/${maxRetries})`;
                    await new Promise(resolve => setTimeout(resolve, 1000));
                  } else {
                    log('达到最大重试次数，放弃抢夺');
                    status.value = '抢夺失败';
                  }
                } else {
                  break;
                }
              }
              await new Promise(resolve => setTimeout(resolve, 3000 + Math.random() * 2000));
              break;
            }
          }
        }
      } else {
        if (refreshUsed >= refreshTotal) {
          // 如果已经找到了目标角色（即使灵石不足），继续等待
          if (targetRole) {
            log(`刷新次数已用尽，继续等待目标角色: ${targetRole.nickname}`);
            status.value = `刷新次数用尽，等待目标: ${targetRole.nickname}`;
            await new Promise(resolve => setTimeout(resolve, 2000 + Math.random() * 2000));
          } else {
            // 只有在没有找到目标角色时，才选择灵石最多的角色
            const maxStoneRole = roleList.reduce((max, role) => {
              const stones = parseFloat(role.stone || 0);
              return stones > parseFloat(max.stone || 0) ? role : max;
            }, { stone: 0 });
  
            if (maxStoneRole.roleId) {
              log(`未找到目标角色，抢夺灵石最高的角色: ${maxStoneRole.nickname} (灵石: ${maxStoneRole.stone})`);
              await executePlunder(maxStoneRole.roleId, maxStoneRole.nickname);
              await new Promise(resolve => setTimeout(resolve, 3000 + Math.random() * 2000));
            } else {
              log('无可用角色，等待10秒后重试');
              status.value = '无可用角色，等待10秒';
              await new Promise(resolve => setTimeout(resolve, 10000 + Math.random() * 2000));
            }
          }
        } else {
          log('未找到满足条件的角色，等待2秒后重试');
          status.value = '未找到目标，等待2秒';
          await new Promise(resolve => setTimeout(resolve, 2000 + Math.random() * 2000));
        }
      }
    }
  
    if (isRunning.value) {
      log('当前时间超出运行时间段，自动停止');
      isRunning.value = false;
      status.value = '已停止（定时）';
      countdown.value = 'N/A';
    }
  };
  
  // 开始抢夺
  const startPlunder = async () => {
    if (isRunning.value) {
      log('已经在运行中');
      return;
    }
  
    if (!config.value.token) {
      log('Token 未设置，请先设置 Token');
      status.value = 'Token 未设置';
      return;
    }
  
    if (!config.value.roleId) {
      log('Role ID 未设置');
      status.value = 'Role ID 未设置';
      return;
    }
  
    if (!config.value.nicknames?.length) {
      log('目标昵称列表为空');
      status.value = '昵称列表为空';
      return;
    }
  
    try {
      isRunning.value = true;
      manuallyStopped.value = false;
      status.value = '正在启动...';
      log('开始运行抢夺程序');
  
      // 开始运行循环
      runCycle();
    } catch (e) {
      console.error('启动失败:', e);
      log('启动失败: ' + e.message);
      status.value = '启动失败';
      isRunning.value = false;
    }
  };
  
  // 停止抢夺
  const stopPlunder = () => {
    uni.showModal({
      title: '确认停止',
      content: '确定要停止自动抢夺吗？',
      success: (res) => {
        if (res.confirm) {
          isRunning.value = false;
          manuallyStopped.value = true;
          status.value = '已停止（手动）';
          countdown.value = 'N/A';
          log('自动抢夺已手动停止');
        }
      }
    });
  };
  
  // 更新配置
  const updateConfig = (newConfig) => {
    try {
      console.log('开始更新配置...');
      const token = newConfig.token?.trim() || '';
      console.log('新配置 token:', {
        exists: !!token,
        length: token?.length,
        value: token ? token.substring(0, 20) + '...' : null
      });
  
      // 直接使用原始昵称数组
      const nicknames = Array.isArray(newConfig.nicknames) ? newConfig.nicknames : [];
      
      if (nicknames.length === 0) {
        log('警告: 昵称列表为空');
        uni.showToast({ title: '昵称列表不能为空', icon: 'none' });
        return;
      }
  
      // 尝试从 token 中解析 uid，但保持原始 token 不变
      const uid = parseTokenUid(token);
      const originalToken = token; // 保存原始 token
  
      // 更新配置，保持原始数据
      config.value = {
        ...newConfig,
        nicknames: nicknames,
        uid: uid || '',  // 如果解析失败，使用空字符串
        roleId: String(newConfig.roleId || ''),
        token: originalToken,  // 使用原始 token
        threshold: String(newConfig.threshold || '168.0'),
        quickRefreshCount: String(newConfig.quickRefreshCount || '3'),
        quickRefreshDuration: String(newConfig.quickRefreshDuration || '40'),
        quickRefreshInterval: String(newConfig.quickRefreshInterval || '4'),
        startTime: String(newConfig.startTime || '10:00'),
        stopTime: String(newConfig.stopTime || '19:00')
      };
  
      // 保存配置
      manuallyStopped.value = false;
      saveConfig();
      log(`配置已更新，token 长度: ${config.value.token?.length || 0}, uid: ${config.value.uid || '未解析'}`);
    } catch (e) {
      console.error('更新配置失败:', e);
      log('更新配置失败: ' + e.message);
    }
  };
  
  // 保存配置
  const saveConfig = () => {
    try {
      const configToSave = {
        ...config.value,
        token: config.value.token?.trim() || ''
      };
      console.log('保存配置:', {
        hasToken: !!configToSave.token,
        tokenLength: configToSave.token?.length,
        tokenValue: configToSave.token ? configToSave.token.substring(0, 20) + '...' : null
      });
      uni.setStorageSync('plunder_config', configToSave);
    } catch (e) {
      console.error('保存配置失败:', e);
      log('保存配置失败: ' + e.message);
    }
  };
  
  // 加载配置
  const loadConfig = () => {
    try {
      const savedConfig = uni.getStorageSync('plunder_config');
      if (savedConfig) {
        config.value = {
          nicknames: Array.isArray(savedConfig.nicknames) ? savedConfig.nicknames : [],
          uid: savedConfig.uid || '',  // 保留 uid
          roleId: String(savedConfig.roleId || ''),
          token: savedConfig.token?.trim() || '',
          threshold: String(savedConfig.threshold || '168.0'),
          quickRefreshCount: String(savedConfig.quickRefreshCount || '3'),
          quickRefreshDuration: String(savedConfig.quickRefreshDuration || '40'),
          quickRefreshInterval: String(savedConfig.quickRefreshInterval || '4')
        };
        // 更新昵称文本框
        nicknameText.value = config.value.nicknames.join('\n');
      }
    } catch (e) {
      console.error('加载配置失败:', e);
    }
  };
  
  // 添加当前时间显示
  const currentTime = ref(new Date().toLocaleTimeString());
  setInterval(() => {
    currentTime.value = new Date().toLocaleTimeString();
  }, 1000);
  
  // 初始化
  onMounted(() => {
    loadConfig();
    // 检查 token 是否有效
    if (!isTokenValid()) {
      log('Token 未设置，请先设置 Token');
      status.value = 'Token 未设置';
    }
    timerId = setInterval(() => {
      if (isRunning.value) {
        secondsToNextFiveMinute();
      }
      checkSchedule();
    }, 1000);
    setInterval(cleanupLogs, LOG_CLEANUP_INTERVAL);
    cleanupLogs();
  });
  
  // 清理定时器
  onUnmounted(() => {
    if (timerId) {
      clearInterval(timerId);
      timerId = null;
    }
  });
  </script>
  
  <style>
  .container {
    padding: 16rpx;
    background-color: #f5f7fa;
    min-height: 100vh;
  }
  
  .control-panel {
    background-color: white;
    border-radius: 12rpx;
    padding: 20rpx;
    margin-bottom: 16rpx;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  }
  
  .panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16rpx;
  }
  
  .panel-title {
    font-size: 28rpx;
    font-weight: 600;
    color: #2c3e50;
  }
  
  .button-group {
    display: flex;
    gap: 8rpx;
  }
  
  .control-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 100rpx;
    height: 56rpx;
    padding: 0 16rpx;
    font-size: 24rpx;
    font-weight: 500;
    border-radius: 6rpx;
    border: none;
    transition: all 0.2s ease;
    white-space: nowrap;
  }
  
  .button-icon {
    font-size: 24rpx;
    margin-right: 4rpx;
  }
  
  .button-primary {
    background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
    color: white;
    box-shadow: 0 2rpx 4rpx rgba(76, 175, 80, 0.2);
  }
  
  .button-danger {
    background: linear-gradient(135deg, #f44336 0%, #e53935 100%);
    color: white;
    box-shadow: 0 2rpx 4rpx rgba(244, 67, 54, 0.2);
  }
  
  .button-secondary {
    background: #f5f7fa;
    color: #606266;
    border: 1rpx solid #dcdfe6;
  }
  
  /* 状态信息样式 */
  .status-info {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200rpx, 1fr));
    gap: 12rpx;
    margin-bottom: 16rpx;
    padding: 12rpx;
    background: #f8f9fa;
    border-radius: 8rpx;
  }
  
  .status-item {
    display: flex;
    align-items: center;
    gap: 8rpx;
  }
  
  .status-label {
    font-size: 22rpx;
    color: #909399;
  }
  
  .status-value {
    font-size: 22rpx;
    color: #2c3e50;
    font-weight: 500;
  }
  
  .status-running {
    color: #67c23a;
  }
  
  .status-active {
    color: #67c23a;
  }
  
  .status-manual-stop {
    color: #909399;
  }
  
  /* 定时设置面板样式 */
  .schedule-panel {
    background: #f8f9fa;
    border-radius: 8rpx;
    padding: 16rpx;
    margin-bottom: 16rpx;
  }
  
  .schedule-header {
    margin-bottom: 12rpx;
  }
  
  .schedule-title {
    font-size: 24rpx;
    font-weight: 600;
    color: #2c3e50;
  }
  
  .schedule-content {
    display: flex;
    flex-direction: column;
    gap: 12rpx;
  }
  
  .time-input-group {
    display: flex;
    gap: 16rpx;
  }
  
  .time-input {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 4rpx;
  }
  
  .time-label {
    font-size: 22rpx;
    color: #606266;
  }
  
  .time-picker {
    background: white;
    border: 1rpx solid #dcdfe6;
    border-radius: 4rpx;
    padding: 8rpx;
    font-size: 22rpx;
    color: #2c3e50;
  }
  
  /* 角色列表样式 */
  .role-list {
    background: white;
    border-radius: 12rpx;
    padding: 16rpx;
    margin-bottom: 16rpx;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  }
  
  .role-list-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12rpx;
  }
  
  .role-list-title {
    font-size: 24rpx;
    font-weight: 600;
    color: #2c3e50;
  }
  
  .role-list-count {
    font-size: 20rpx;
    color: #909399;
  }
  
  .role-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260rpx, 1fr));
    gap: 12rpx;
  }
  
  .role-card {
    background: #f8f9fa;
    border-radius: 8rpx;
    padding: 12rpx;
    transition: all 0.2s ease;
  }
  
  .role-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8rpx;
  }
  
  .role-nickname {
    font-size: 22rpx;
    font-weight: 600;
    color: #2c3e50;
  }
  
  .role-stone {
    font-size: 20rpx;
    color: #909399;
  }
  
  .role-stone.highlight {
    color: #67c23a;
    font-weight: 500;
  }
  
  .role-info {
    display: flex;
    flex-direction: column;
    gap: 4rpx;
  }
  
  .role-level {
    font-size: 20rpx;
    color: #409eff;
    font-weight: 500;
  }
  
  .role-detail {
    font-size: 18rpx;
    color: #606266;
  }
  
  .role-equip {
    font-size: 18rpx;
    color: #909399;
    margin-top: 4rpx;
  }
  
  /* 提示信息样式 */
  .tips {
    background: #fdf6ec;
    border-radius: 8rpx;
    padding: 16rpx;
    margin-bottom: 16rpx;
    display: flex;
    align-items: flex-start;
    gap: 8rpx;
    border-left: 4rpx solid #e6a23c;
  }
  
  .tips-icon {
    font-size: 24rpx;
  }
  
  .tips-content {
    flex: 1;
    font-size: 22rpx;
    color: #e6a23c;
    line-height: 1.4;
  }
  
  @media screen and (min-width: 768px) {
    .container {
      max-width: 1200rpx;
      margin: 0 auto;
      padding: 24rpx;
    }
  
    .role-grid {
      grid-template-columns: repeat(auto-fill, minmax(280rpx, 1fr));
    }
  
    .status-info {
      grid-template-columns: repeat(4, 1fr);
    }
  }
  </style>